<template>
    <div class="hls-player-container">
        <!-- 视频容器 -->
        <video ref="videoElement" class="video-js" controls playsinline></video>

        <!-- 加载状态 -->
        <div v-if="state.loading" class="overlay loading">
            <div class="spinner"></div>
            <span>视频加载中...</span>
        </div>

        <!-- 错误状态 -->
        <div v-if="state.error" class="overlay error">
            <span>{{ state.errorMessage }}</span>
            <el-button type="primary" @click="retry">重试</el-button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
import Hls from 'hls.js'

const props = defineProps({
    src: {
        type: String,
        required: true
    },
    autoplay: {
        type: Boolean,
        default: false
    }
})

const videoElement = ref<HTMLVideoElement>()
const state = reactive({
    loading: true,
    error: false,
    errorMessage: '',
    retryCount: 0,
    maxRetries: 3
})

let player: videojs.Player | null = null
let hls: Hls | null = null

// 初始化播放器
const initPlayer = () => {
    if (!videoElement.value) return

    player = videojs(videoElement.value, {
        autoplay: props.autoplay,
        controls: true,
        liveui: true,
        html5: {
            hls: {
                overrideNative: true
            }
        }
    })

    setupHls()
}

// 设置HLS播放
const setupHls = () => {
    if (!player) return

    // 检查浏览器原生支持
    if (videoElement.value?.canPlayType('application/vnd.apple.mpegurl')) {
        player.src({
            src: props.src,
            type: 'application/vnd.apple.mpegurl'
        })
        player.on('error', handlePlayerError)
    }
    // 使用hls.js
    else if (Hls.isSupported()) {
        hls = new Hls({
            maxMaxBufferLength: 30,
            enableWorker: true
        })

        hls.on(Hls.Events.ERROR, handleHlsError)
        hls.on(Hls.Events.MANIFEST_PARSED, () => {
            state.loading = false
        })

        hls.loadSource(props.src)
        hls.attachMedia(videoElement.value)
    }
    // 不支持HLS
    else {
        handleError('您的浏览器不支持HLS视频播放')
    }
}

// 错误处理
const handleHlsError = (event: any, data: any) => {
    if (data.fatal) {
        switch (data.type) {
            case Hls.ErrorTypes.NETWORK_ERROR:
                handleError('网络错误，正在尝试重新连接...')
                break
            case Hls.ErrorTypes.MEDIA_ERROR:
                hls?.recoverMediaError()
                return
            default:
                handleError('视频加载失败')
        }
    }
}

const handlePlayerError = () => {
    handleError('视频播放错误')
}

const handleError = (message: string) => {
    state.error = true
    state.errorMessage = message
    state.loading = false

    if (state.retryCount < state.maxRetries) {
        setTimeout(() => {
            state.retryCount++
            reloadPlayer()
        }, 2000 * state.retryCount)
    }
}

// 重新加载播放器
const reloadPlayer = () => {
    state.error = false
    state.loading = true

    if (hls) {
        hls.destroy()
        hls = null
    }

    setupHls()
}

// 重试
const retry = () => {
    state.retryCount = 0
    reloadPlayer()
}

onMounted(() => {
    initPlayer()
})

onUnmounted(() => {
    if (hls) hls.destroy()
    if (player) player.dispose()
})
</script>

<style scoped>
/* .hls-player-container {
    position: relative;
    width: 100%;
    height: 100vh;
}

.video-js {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
} */

.hls-player-container {
    position: relative;
    width: 100%;
    height: 100vh;
    overflow: hidden; /* 防止滚动条 */
}

/* 关键修改：让视频填满容器并裁剪多余部分 */
:deep(.video-js .vjs-tech) {
    object-fit: cover !important;
    width: 100% !important;
    height: 100% !important;
}

/* 确保 video.js 容器也占满 */


.video-js {
    position: absolute;
    top: 0;
    left: 0;
    width: 100% !important;
    height: 100% !important;
}

/* 新增采集区域虚线框 */
/* .video-js::after {
    content: '';
    position: absolute;
    top: 20px;
    left: 20px;
    right: 20px;
    bottom: 20px;
    border: 2px dashed red;
    pointer-events: none;
    z-index: 1;
} */

.overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: rgba(0, 0, 0, 0.7);
    color: white;
    z-index: 2;
    /* 确保覆盖在虚线框上方 */
}

.loading .spinner {
    width: 40px;
    height: 40px;
    border: 4px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    border-top-color: #fff;
    animation: spin 1s linear infinite;
    margin-bottom: 10px;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}
</style>